package com.dayu.finecomm.utils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Calendar;
import java.util.Date;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

public class Helpers {

	private static final char[] TBL = new char[256 * 4];

	static {

		final char[] DIGITS = "0123456789ABCDEF".toCharArray();

		for (int i = 0; i < 256; i++) {

			TBL[i << 1] = DIGITS[i >>> 4 & 0x0F];
			TBL[(i << 1) + 1] = DIGITS[i & 0x0F];
		}
	}

	public static String host(ChannelHandlerContext ctx) {

		InetSocketAddress sa = (InetSocketAddress) ctx.channel().remoteAddress();
		return sa.getAddress().toString() + ":" + sa.getPort();
	}

	public static byte[] hexToBytes(String hex) {

		int state = 0;
		int v = 0;

		ByteBuffer bb = ByteBuffer.allocate(hex.length() / 2 + 1);

		for (char ch : hex.toCharArray()) {

			if (state == 2 || ch == ' ') {
				bb.put((byte) v);
				v = 0;
				state = 0;
			}

			if (ch >= 'a' && ch <= 'f') {
				state++;
				v = v * 16 + ch - 'a' + 10;
			} else if (ch >= 'A' && ch <= 'F') {
				state++;
				v = v * 16 + ch - 'A' + 10;
			} else if ((ch >= '0' && ch <= '9')) {
				state++;
				v = v * 16 + ch - '0';
			}
		}

		if (state > 0) {
			bb.put((byte) v);
		}

		byte[] kk = new byte[bb.position()];
		bb.flip();
		bb.get(kk);
		return kk;
	}

	/***
	 * parse date
	 * 
	 * @param format
	 * @param val
	 * @return
	 */
	public static long parseDate(String format, String val) {

		try {
			SimpleDateFormat f = new SimpleDateFormat(format);
			return f.parse(val).getTime();
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}

	/***
	 * format date
	 * 
	 * @param format
	 *            i.e. yyyy-MM-dd
	 * @param val
	 *            date-val
	 * @return string of date in format
	 */
	public static String formatDate(String format, Date val) {

		SimpleDateFormat f = new SimpleDateFormat(format);
		return f.format(val);
	}

	/***
	 * BCD: <b>单字节</b> - 8421
	 * 
	 * @return 0x12 = 12 , 0x99 = 99, 0x01 = 1
	 */
	public static int BCD(short b) {
		return ((b >>> 4) & 0xf) * 10 + (b & 0xf);
	}

	/***
	 * BCD数组 转 INT
	 * 
	 * 按字节*100,例如 0x01 0x01 => 1*100 + 1 => 101
	 * 
	 * @return
	 */
	public static long bcdBytes2Long(ByteBuf in, int length) {

		long val = 0;

		for (int i = 0; i < length; i++) {

			val = val * 100 + in.readUnsignedByte();
		}

		return val;
	}

	/***
	 * 是否需要主动校时
	 * 
	 * @return
	 */
	public static boolean needTiming() {

		// 每周三定点校时
		Calendar cal = Calendar.getInstance();

		if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) {
			if (cal.get(Calendar.HOUR_OF_DAY) == 3 && cal.get(Calendar.MINUTE) < 5) {
				return true;
			}
		}

		return false;
	}

	public static int crc16(byte[]... bs) {

		ACRC16 x = new ACRC16();

		for (byte[] b : bs) {
			x.update(b);
		}

		return x.value();
	}

	public static int crc16(ByteBuf... bs) {

		ACRC16 x = new ACRC16();

		for (ByteBuf b : bs) {

			for (int i = 0; i < b.readableBytes(); i++) {
				x.update(b.getByte(i));
			}
		}

		return x.value();
	}

	public static String bytesToHex(ByteBuf bs) {

		StringBuilder sb = new StringBuilder();

		for (int j = 0; j < bs.readableBytes(); j++) {

			int i = bs.getUnsignedByte(j) << 1;
			sb.append(TBL[i]).append(TBL[i + 1]);
			sb.append(" ");
		}

		return sb.toString();

	}

	public static String bytesToHexString(ByteBuf bs) {

		StringBuilder sb = new StringBuilder();

		for (int j = 0; j < bs.readableBytes(); j++) {

			int i = bs.getUnsignedByte(j) << 1;
			sb.append(TBL[i]).append(TBL[i + 1]);
		}

		return sb.toString();

	}

	public static String bytesToHex(byte[] bs) {

		StringBuilder sb = new StringBuilder();

		for (byte b : bs) {

			int i = (b & 0xff) << 1;
			sb.append(TBL[i]).append(TBL[i + 1]);
			sb.append(" ");
		}

		return sb.toString();
	}

	public static String bytesToHexString(byte[] bs) {

		StringBuilder sb = new StringBuilder();

		for (byte b : bs) {

			int i = (b & 0xff) << 1;
			sb.append(TBL[i]).append(TBL[i + 1]);
		}

		return sb.toString();
	}

	public static String byteToHexString(byte b) {

		StringBuilder sb = new StringBuilder();

		int i = (b & 0xff) << 1;
		sb.append(TBL[i]).append(TBL[i + 1]);

		return sb.toString();
	}

	private static int toByte(char c) {
		if (c >= '0' && c <= '9')
			return (c - '0');
		if (c >= 'A' && c <= 'F')
			return (c - 'A' + 10);
		if (c >= 'a' && c <= 'f')
			return (c - 'a' + 10);

		throw new RuntimeException("Invalid hex char '" + c + "'");
	}

	/**
	 * bcd码形式的16进制
	 * 
	 * @param hexString
	 * @return
	 */
	public static byte[] hexStringToBytes(String hexString) {
		int length = hexString.length();
		byte[] buffer = new byte[length / 2];

		for (int i = 0; i < length; i += 2) {
			buffer[i / 2] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1)));
		}

		return buffer;
	}

	/**
	 * 有空格的bcd码转bytes
	 * 
	 */
	public static byte[] hexSpaceToBytes(String hexString) {
		String[] ss = hexString.split(" ");
		int len = ss.length;
		byte[] buffer = new byte[len];

		for (int i = 0; i < len; i++) {
			buffer[i] = (byte) ((toByte(ss[i].charAt(0)) << 4) | toByte(ss[i].charAt(1)));
		}
		return buffer;
	}

	public static byte[] intToBytes(int a) {

		return new byte[] { (byte) ((a >> 24) & 0xFF), (byte) ((a >> 16) & 0xFF), (byte) ((a >> 8) & 0xFF),
				(byte) (a & 0xFF) };
	}

	/**
	 * 高位在前，低位在后 4字节
	 */
	public static int bytesToInt(byte[] src) {
		int value;
		value = ((src[0] & 0xFF) << 24) | ((src[1] & 0xFF) << 16) | ((src[2] & 0xFF) << 8) | (src[3] & 0xFF);
		return value;
	}

	/**
	 * 有符号短整型，高位在前，低位在后
	 * 
	 * @param b
	 * @return
	 */
	public static short byteToShort(byte[] b) {
		return (short) (((b[0] & 0xff) << 8) | (b[1] & 0xff));
	}

	public static int byteToInt(byte b) {

		return b & 0xFF;
	}

	/**
	 * 16进制左边自动补0x00
	 * 
	 * @param ss
	 * @param length
	 * @return
	 */
	// public static byte[] padLeft(byte[] ss, int length) {
	//
	// byte[] bs = new byte[length];
	// System.arraycopy(ss, 0, bs, length - ss.length, ss.length);
	//
	// return bs;
	// }

	/**
	 * 合并2个字节数组
	 */
	public static byte[] byteMerger(byte[] byte_1, byte[] byte_2) {
		byte[] byte_3 = new byte[byte_1.length + byte_2.length];
		System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
		System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
		return byte_3;
	}

	/**
	 * 合并3个字节数组
	 */
	public static byte[] byteMerger(byte[] byte1, byte[] byte2, byte[] byte3) {
		byte[] bytes = new byte[byte1.length + byte2.length + byte3.length];
		System.arraycopy(byte1, 0, bytes, 0, byte1.length);
		System.arraycopy(byte2, 0, bytes, byte1.length, byte2.length);
		System.arraycopy(byte3, 0, bytes, byte1.length + byte2.length, byte3.length);
		return bytes;
	}

	/**
	 * base64为解密
	 */
	public static byte[] decodeBase64(String str) {
		byte[] bt = null;
		bt = java.util.Base64.getDecoder().decode(str);
		//sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
		//bt = decoder.decodeBuffer(str);
		return bt;
	}

	/**
	 * base64为加密
	 */
	public static String encodeBASE64(String s) {

		if (s == null)
			return null;

		try {
			return Base64.getEncoder().encodeToString((s.getBytes("UTF-8")));
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * byte数组反转
	 * 
	 * @param src
	 *            原数组
	 * @return 目标数组
	 */
	public static byte[] reverseBytes(byte[] src) {

		int len = src.length;
		byte[] des = new byte[len];

		for (int i = 0; i < len; i++) {
			des[i] = src[len - 1 - i];
		}

		return des;
	}

	public static Charset ASCII = Charset.forName("ASCII");
	public static Charset UTF8 = Charset.forName("utf-8");
}
